package OOPAndMultiThreadArchiveManager.Client.Views;

import OOPAndMultiThreadArchiveManager.Client.Controllers.HttpController;
import OOPAndMultiThreadArchiveManager.Client.Models.ApiReceive;
import OOPAndMultiThreadArchiveManager.Client.Models.ApiResponse;
import OOPAndMultiThreadArchiveManager.Client.Models.UserChange;
import OOPAndMultiThreadArchiveManager.Client.Models.UserInfo;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CompletableFuture;

public class UserManageView {
    private final String[] roles = new String[]{"Administrator", "Operator", "Browser"};
    private final Vector<String> columns = new Vector<>(List.of(new String[]{"账号", "密码", "角色"}));
    private JTabbedPane UserManageTabbedPane;
    private JPanel panel1;
    private JPanel newUserPanel;
    private JPanel changeUserPanel;
    private JPanel deleteUserPanel;
    private JTextField newUserUserName;
    private JPasswordField newUserPassword;
    private JComboBox<String> newUserComboBox;
    private JButton newUserButton;
    private JComboBox<String> changeUserUserNameComboBox;
    private JPasswordField changeUserPasswordField;
    private JComboBox<String> changeUserRoleComboBox;
    private JButton changeUserButton;
    private JTable table;
    private JButton deleteUserButton;
    private JFrame frame;
    private UserInfo userInfo;
    private ObjectMapper objectMapper = new ObjectMapper();
    private Vector<UserInfo> allUsers = new Vector<>();
    private Vector<String> userNames = new Vector<>();
    private Vector<Vector<String>> allUsersArray = new Vector<>();

    public UserManageView(UserInfo userInfo, int index) {
        this.userInfo = userInfo;
        getAllUsersAsync();

        table.getTableHeader().setReorderingAllowed(false);
        table.setModel(new DefaultTableModel(allUsersArray, columns) {
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        });
        newUserComboBox.setModel(new DefaultComboBoxModel<>(roles));
        changeUserUserNameComboBox.setModel(new DefaultComboBoxModel<>(userNames));
        changeUserRoleComboBox.setModel(new DefaultComboBoxModel<>(roles));

        UserManageTabbedPane.setSelectedIndex(index);
        UserManageTabbedPane.addChangeListener(e -> getAllUsersAsync());
        newUserButton.addActionListener(e -> signInAsync());
        changeUserButton.addActionListener(e -> changeUserInfoAsync());
        deleteUserButton.addActionListener(e -> deleteUserAsync());

        frame = new JFrame("UserManageView");
        frame.setContentPane(panel1);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.pack();
        frame.setSize(600, 360);
        frame.setLocationRelativeTo(panel1);
        frame.setVisible(true);
    }

    private void signInAsync() {
        var request = new ApiReceive();
        request.user.name = userInfo.user;
        request.user.password = userInfo.password;
        request.api = ApiReceive.Api.POST_User;

        var signInUserInfo = new UserInfo();
        signInUserInfo.user = newUserUserName.getText();
        signInUserInfo.password = String.valueOf(newUserPassword.getPassword());
        signInUserInfo.role = (String) newUserComboBox.getModel().getSelectedItem();
        request.data = signInUserInfo;

        CompletableFuture.supplyAsync(() -> new HttpController().Request(request))
                .whenCompleteAsync(((response, throwable) -> {
                    if (response.apiCode == ApiResponse.ApiCode.Success) {
                        JOptionPane.showMessageDialog(frame, "注册成功！");
                    } else if (response.apiCode == ApiResponse.ApiCode.Unauthorized) {
                        JOptionPane.showMessageDialog(frame, "验证失败，请检查你的账号和密码。");
                    } else if (response.apiCode == ApiResponse.ApiCode.Failed) {
                        JOptionPane.showMessageDialog(frame, objectMapper.convertValue(response.data, String.class));
                    }
                }));
    }

    private void getAllUsersAsync() {
        var request = new ApiReceive();
        request.user.name = userInfo.user;
        request.user.password = userInfo.password;
        request.api = ApiReceive.Api.GET_UserList;
        CompletableFuture.supplyAsync(() -> new HttpController().Request(request))
                .whenCompleteAsync(((response, throwable) -> {
                    if (response.apiCode == ApiResponse.ApiCode.Success) {
                        allUsers = objectMapper.convertValue(response.data, new TypeReference<Vector<UserInfo>>(){});
                        userNames.clear();
                        allUsersArray.clear();
                        for (UserInfo userInfo : allUsers) {
                            userNames.add(userInfo.user);
                            allUsersArray.add(new Vector<>(List.of(new String[]{userInfo.user, userInfo.password, userInfo.role})));
                        }
                    } else if (response.apiCode == ApiResponse.ApiCode.Unauthorized) {
                        JOptionPane.showMessageDialog(frame, "验证失败，请检查你的账号和密码。");
                    }
                    table.setModel(new DefaultTableModel(allUsersArray, columns) {
                        @Override
                        public boolean isCellEditable(int row, int column) {
                            return false;
                        }
                    });
                    changeUserUserNameComboBox.setModel(new DefaultComboBoxModel<>(userNames));
                }));
    }

    private void changeUserInfoAsync() {
        var request = new ApiReceive();
        request.user.name = userInfo.user;
        request.user.password = userInfo.password;
        request.api = ApiReceive.Api.PUT_User;

        var changedUserInfo = new UserInfo();
        changedUserInfo.user = (String) changeUserUserNameComboBox.getModel().getSelectedItem();
        changedUserInfo.password = String.valueOf(changeUserPasswordField.getPassword());
        changedUserInfo.role = (String) changeUserRoleComboBox.getModel().getSelectedItem();

        var userChange = new UserChange();
        userChange.changedUserInfo = changedUserInfo;
        userChange.originUserName = (String) changeUserUserNameComboBox.getModel().getSelectedItem();

        request.data = userChange;
        CompletableFuture.supplyAsync(() -> new HttpController().Request(request))
                .whenCompleteAsync(((response, throwable) -> {
                    if (response.apiCode == ApiResponse.ApiCode.Success) {
                        JOptionPane.showMessageDialog(frame, "修改用户信息成功！");
                    } else if (response.apiCode == ApiResponse.ApiCode.Unauthorized) {
                        JOptionPane.showMessageDialog(frame, "验证失败，请检查你的账号和密码。");
                    } else if (response.apiCode == ApiResponse.ApiCode.Failed) {
                        JOptionPane.showMessageDialog(frame, objectMapper.convertValue(response.data, String.class));
                    }
                }));
    }

    public void deleteUserAsync() {
        for (int i = 0; i < 3; i++) {
            if (table.isColumnSelected(i)) {
                break;
            } else if (i == 2) {
                return;
            }
        }

        var option = JOptionPane.showConfirmDialog(frame, "请再次确认是否删除用户 " + table.getValueAt(table.getSelectedRow(), 0), "提示", JOptionPane.YES_NO_OPTION);
        if (option != JOptionPane.OK_OPTION) {
            JOptionPane.showMessageDialog(frame, "删除用户操作已取消");
            return;
        }

        var request = new ApiReceive();
        request.user.name = userInfo.user;
        request.user.password = userInfo.password;
        request.api = ApiReceive.Api.DELETE_User;

        request.data = table.getValueAt(table.getSelectedRow(), 0);
        CompletableFuture.supplyAsync(() -> new HttpController().Request(request))
                .whenCompleteAsync(((response, throwable) -> {
                    if (response.apiCode == ApiResponse.ApiCode.Success) {
                        JOptionPane.showMessageDialog(frame, "成功删除用户！");
                    } else if (response.apiCode == ApiResponse.ApiCode.Unauthorized) {
                        JOptionPane.showMessageDialog(frame, "验证失败，请检查你的账号和密码。");
                    } else if (response.apiCode == ApiResponse.ApiCode.Failed) {
                        JOptionPane.showMessageDialog(frame, objectMapper.convertValue(response.data, String.class));
                    }
                }))
                .whenComplete(((response, throwable) -> getAllUsersAsync()));
    }
}
